/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.classdiagram.editpart;

import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.draw2d.text.TextFlow;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;
import org.eclipse.gef.tools.CellEditorLocator;
import org.eclipse.gef.tools.DirectEditManager;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.uml2.uml.Constraint;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.ElementImport;
import org.eclipse.uml2.uml.LiteralString;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.UMLFactory;

import com.cea.papyrus.core.PapyrusPlugin;
import com.cea.papyrus.core.directedit.FigureControler;
import com.cea.papyrus.core.directedit.ILabelControler;
import com.cea.papyrus.core.directedit.MultilineLabelDirectEditManager;
import com.cea.papyrus.core.directedit.PropertyAccessor;
import com.cea.papyrus.core.directedit.SimpleCellEditorLocator;
import com.cea.papyrus.core.directedit.TextFlowCellEditorLocator;
import com.cea.papyrus.core.editor.ModelManager;
import com.cea.papyrus.core.editpart.GraphNodeWithSemanticEditPart;
import com.cea.papyrus.core.figures.IconFigure;
import com.cea.papyrus.core.figures.NodeFigure;
import com.cea.papyrus.core.preference.CommonPreferenceConstants;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.diagram.classdiagram.figures.ConstraintFigure;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;
import com.cea.papyrus.umlutils.ICustomAppearence;

/**
 * This is the controler of the {@link Constraint}.
 * 
 * @author PT202707
 */
public class ConstraintEditPart extends GraphNodeWithSemanticEditPart {

	/**
	 * Manager for editing the comment.
	 */
	protected DirectEditManager manager;

	/**
	 * Default constructor.
	 * 
	 * @param modelManager model manager for this element
	 * @param graphNode model graph node for this edit part
	 */
	public ConstraintEditPart(GraphNode graphNode,ModelManager modelManager) {
		super(graphNode,modelManager);
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.core.common.editpart.GraphNodeWithSemanticEditPart#createFigure()
	 */
	/**
	 * 
	 * 
	 * @return 
	 */
	@Override
	protected IFigure createFigure() {
		// Force initialization of the manager when figure has changed
		manager = null;	
		// Try to get figure from ContainerWithSemanticEditPart
		IFigure fig = super.createFigure();
		if (fig != null) {
			return fig;
		}
		// else
		return new ConstraintFigure();		
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.core.common.editpart.GraphNodeWithSemanticEditPart#refreshVisuals()
	 */
	/**
	 * 
	 */
	@Override
	protected void refreshVisuals() {
		Debug.debug(this, "refreshvisuals", channel);

		IPreferenceStore store = PapyrusPlugin.getDefault().getPreferenceStore();	
		
		Dimension size = getGraphNode().getSize();
		Point p = getGraphNode().getPosition();
		Rectangle r = new Rectangle(p ,size);

		IFigure fig = getFigure();

		// if fig is a stereotype figure
		if (!(fig instanceof ConstraintFigure)) {
			IconFigure icf= (IconFigure) getFigure();
			icf.setName(((NamedElement)getUmlElement()).getName());

		} else {
			org.eclipse.uml2.uml.Constraint currentConstraint = getUmlElement();
			com.cea.papyrus.umlutils.Element currentElement = new com.cea.papyrus.umlutils.Element(getUmlElement());

			// Retrieve current class and figure
			ConstraintFigure f = (ConstraintFigure) fig; //get Class figure
			// f.setName(currentConstraint.getName());//set the name

			int style = 0;
			com.cea.papyrus.diagraminterchange2.di2.Property prop = getGraphNode().getProperty(ICustomAppearence.CUSTOM_APPEARENCE_KEY);
			String value = "";
			// no special property
			if(prop == null) {
				style = loadPreferenceStyle(store);
			} else {
				// custom property: get the style for this property 
				value = prop.getValue();
				if(value != null) {
					try {
						style = Integer.parseInt(value);
					} catch (NumberFormatException e) {
						Debug.log(e);
					}
				}
			}

			String newText = com.cea.papyrus.umlutils.Constraint.getCustomLabel(currentConstraint, style);

			
			f.setConstraint(newText);

			// if fig is a ClassFigure
			((NodeFigure) fig).refreshColors(getGraphNode());
			// set additionnal graphical parameter
			f.setfigureFont(getGraphNode().getFontFamily());
			f.setFontSize((getGraphNode().getFontSize()));
			f.setLineThickness((getGraphNode().getLineThickness()));

			((NodeFigure) fig).refreshPresentation(getPresentation(), currentConstraint, getGraphNode());
			boolean hasIcon  = currentElement.hasIcon();
			boolean hasShape = currentElement.hasShape();
			//f.refreshStereotypes(currentElement.getStereotypes(), getPresentation(), hasIcon, hasShape);
			f.refreshStereotypes(f.stereotypesLabel(this), getPresentation(), hasIcon, hasShape);

		}

		((GraphicalEditPart) getParent()).setLayoutConstraint(
				this,
				fig,
				r);
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.core.common.editpart.GraphNodeWithSemanticEditPart#getUmlElement()
	 */
	/**
	 * 
	 * 
	 * @return 
	 */
	@Override
	public org.eclipse.uml2.uml.Constraint getUmlElement() {
		Element e=((Uml1SemanticModelBridge)getGraphNode().getSemanticModel()).getElement();
		// case of element import
		if(e instanceof ElementImport){
			return (org.eclipse.uml2.uml.Constraint)((ElementImport) e).getImportedElement();
		}
		// this is a simple Constraint
		return (org.eclipse.uml2.uml.Constraint)e;
	}
	
	/**
	 * Init the label direct edit manager.
	 * This method should be called when a Direct Edit request is performed.
	 */
	protected void initLabelEditManager() {
		if(manager==null) {
			// locator for the cell editor (on the name label)
			CellEditorLocator locator = null;
			final IFigure textFigure = getTextFigure();
			if(textFigure instanceof TextFlow) {
				locator = new TextFlowCellEditorLocator((TextFlow)textFigure);
			} else {
				locator = new SimpleCellEditorLocator(textFigure);
			}

			// defining how properties are modified in the model
			PropertyAccessor accessor = new PropertyAccessor() {
				public String getPropertyName() {
					return "Constraint Specification";
				}
				
				public String getValue() {
					Constraint constraint = getUmlElement();

					if (constraint.getSpecification() != null) {
						return constraint.getSpecification().stringValue();
					}

					return "";
				}
				public void setValue(String value) {
					Constraint constraint = getUmlElement();
					LiteralString constraintBody = UMLFactory.eINSTANCE.createLiteralString();
					constraintBody.setValue(value);
					constraintBody.setName("constraintBody");

					if (constraint.getSpecification() == null) {
						constraint.createSpecification("specification", null, UMLFactory.eINSTANCE.getUMLPackage().getLiteralString());
						constraint.setSpecification(constraintBody);		
					} else {
						constraint.setSpecification(constraintBody);	
					}	
				}
			};
			// defines the controler: link between model and view
			ILabelControler labelControler = new FigureControler(getTextFigure(), accessor);

			// creates the editing manager.
			manager = new MultilineLabelDirectEditManager(this, locator, labelControler);
		}
	}
	
	/**
	 * 
	 * 
	 * @return 
	 */
	protected IFigure getTextFigure() {
		IFigure fig = getFigure();
		
		if (fig instanceof IconFigure) {
			return (Label) fig;
		} else if (fig instanceof ConstraintFigure) {
			return ((ConstraintFigure) fig).getTextFigure();
		} else {
			Debug.error(this, "ConstraintEditPart::getTextFigure() : Unknown Figure type.", channel);
			return null;
		}
	}
	
	/**
	 * the direct edit mechanism requires the edit part to handle the direct edit
	 * request.
	 * 
	 * @param req the request that called the direct edit.
	 */
	public void performDirectEdit(Request req) {
		initLabelEditManager();
		manager.show();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.gef.editparts.AbstractEditPart#performRequest(org.eclipse.gef.Request)
	 */
	/**
	 * 
	 * 
	 * @param request 
	 */
	@Override
	public void performRequest(Request request){
		if (RequestConstants.REQ_DIRECT_EDIT.equals(request.getType())) {
			performDirectEdit(request);
		}
	}
	
	/**
	 * Returns default display from preference store
	 * @param store the preference store
	 * @return default display from preference store
	 */
	private int loadPreferenceStyle(IPreferenceStore store) {
		int style = 0;
		
		if (CommonPreferenceConstants.getPreferenceConstraintNameAppearance(store)){
			style = style | ICustomAppearence.DISP_NAME;
		}
		
		if (CommonPreferenceConstants.getPreferenceConstraintBodyAppearance(store)){
			style = style | ICustomAppearence.DISP_BODY;
		}
		
		return style;
	}
}
